//: Playground - noun: a place where people can play

import UIKit

//: ## 可选性
//: > Swift 的可选型可以用来表示可能缺失或者计算失败的值。

let cities = ["beijing":1010,"shanghai":30430,"shenzhen":2939,"guangzhou":294]

//: ### 如果键值不存在则为 nil 空
let foshan = cities["foshan"]

//: 推荐使用可选型
let foshan1: Int? = cities["foshan"]

let beijing: Int? = cities["beijing"]

//: ### 可选型的解包方式

//: #### 1.强制解包

let beijingPopulation = beijing!

//: #### 2.可选绑定机制（Optional binding）

if let beijingPopulation1 = cities["beijing"] {
    print("北京人口是\(beijingPopulation1)")
} else {
    print("未知城市")
}

//: #### 3. ??运算符，让强制解包更安全

// 尝试重写 ?? 运算符

//infix operator ??
//
//func ??<T>(optional: T?, defaultValue: T) -> T {
//    if let x = optional {
//        return x
//    } else {
//        return defaultValue
//    }
//}

let beijingPopulation2 = cities["beijing"] ?? 1000
let foshan2 = cities["foshan"] ?? 1000

//: #### 上面代码我们还需要花费成本运算 defaultValue 的值，可是如果我们的可选值不为 nil 时是不需要运算 ?? 之后的代码

func ??<T>(optional: T?, defaultValue: () -> T) -> T {
    if let x = optional {
        return x
    } else {
        return defaultValue()
    }
}

cities["foshan"] ?? { 1000 }

//: #### 默认创建一个显示的闭包，有点不理想

//infix operator ?? { associativity right precedence 110 }

func ??<T>(optional: T?, @autoclosure defaultValue: () -> T) -> T {
    if let x = optional {
        return x
    } else {
        return defaultValue()
    }
}

cities["foshan"] ?? 1000 * 2992 // 隐身闭包

// 可选值链

struct Order {
    let orderNumber: Int
    let person: Person?
}

struct Person {
    let name: String
    let address: Address?
}

struct Address {
    let streetName: String
    let city: String
    let state: String?
}

let order = Order(orderNumber: 101, person: Person(name: "asd", address: Address(streetName: "asd", city: "asd", state: "asd")))

// 默认情况
order.person?.address?.state
// 强制解包
order.person!.address!.state!

// 可选绑定（略麻烦）
if let myPerson = order.person {
    if let myAddress = myPerson.address {
        if let myState = myAddress.state {
            print(myState)
        }
    }
}

// 可选值链解包

if let myState = order.person?.address?.state {
    print("国家是\(myState)")
}else{
    print("未知用户，地址，国家")
}

//: #### 4. 分支上的可选值 —— Switch

let yantai: Int? = cities["yantai"]
let shenzhen: Int? = cities["shenzhen"]

switch yantai {
case 0?: print("没人在烟台")
case (1..<1000)?: print("少于1000000人")
case .Some(let x): print("有\(x)在烟台")
case .None: print("我不清楚烟台的情况")
}

switch shenzhen {
case .Some(let x): print("有\(x)在深圳")
case .None: print("不清楚深证的情况")
}

// .Some 匹配到可选值的值，.None 匹配可选值为 nil

//: #### 5.分支上的可选值 —— guard

// guard 语句的设计在当一些条件不满足时，可以尽早退出当前作用域

func getCityPopulation(city: String) -> String? {
    guard let population = cities[city] else {
        return nil
    }
    return "\(city)的人口是\(population)"
}

getCityPopulation("shenzhen")
getCityPopulation("yantai")

//: ### 可选映射

extension Optional {
    func map<T>(transform: Wrapped -> T) -> T? {
        guard let x = self else { return nil }
        return transform(x)
    }
}

shenzhen.map{ $0 + 1}






